home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / GL / bounce / bounce.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  14KB  |  773 lines

  1. /*
  2.  * Copyright (C) 1991, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  */
  5. /**************************************************************************
  6.  *                                      *
  7.  *      Copyright (C) 1988, 1989, 1990, Silicon Graphics, Inc.          *
  8.  *                                      *
  9.  *  These coded instructions, statements, and computer programs  contain  *
  10.  *  unpublished  proprietary  information of Silicon Graphics, Inc., and  *
  11.  *  are protected by Federal copyright law.  They  may  not be disclosed  *
  12.  *  to  third  parties  or copied or duplicated in any form, in whole or  *
  13.  *  in part, without the prior written consent of Silicon Graphics, Inc.  *
  14.  *                                      *
  15.  **************************************************************************/
  16.  
  17. /*
  18.  *  foo $Revision: 1.16 $
  19.  */
  20. #include "math.h"
  21. #include "stdio.h"
  22. #include "gl.h"
  23. #include "device.h"
  24.  
  25. #define UDIV 12
  26. #define VDIV 12
  27.  
  28. #define WALLGRID 8
  29. #define EYEZ 3.3
  30.  
  31. #define TOTALBALLS 3
  32.  
  33. #define R 0
  34. #define G 1
  35. #define B 2
  36.  
  37. #define X 0
  38. #define Y 1
  39. #define Z 2
  40. #define W 3
  41.  
  42. int freeze = FALSE;
  43. int spin = FALSE;
  44. int objecton = FALSE;
  45. int normson = FALSE;
  46. int lighton[3] = {TRUE, TRUE, TRUE};
  47.  
  48. struct {
  49.    float p[3];
  50.    float d[3];
  51.    int color[3];
  52. } balls[TOTALBALLS];
  53.  
  54. float ballobj[UDIV+1][VDIV+1][4];
  55. float wallobj[WALLGRID+1][WALLGRID+1][4];
  56. float wallnorms[WALLGRID+1][WALLGRID+1][3];
  57. float wallnorm[3] = { 0.0, 0.0, -1.0 };
  58.  
  59. int rx, ry;
  60. int orx, ory;
  61.  
  62. float ballscale;
  63. float ballsize;
  64.  
  65. long xsize, ysize;
  66.  
  67. int menu = 0;
  68. int lflag = 0;
  69.  
  70. char machinetype[12];
  71. static enum {
  72.     MACH_G, 
  73.     MACH_GT, 
  74.     MACH_VGX, 
  75.     MACH_PI
  76. } machine;
  77.  
  78. float rotm[3][3],rotmi[3][3],curmat[3][3];
  79.  
  80. float light1[] = {
  81.    AMBIENT,  0.0, 0.0, 0.0,
  82.    LCOLOR,   1.0, 0.1, 0.1,
  83.    POSITION, 0.0, 0.0, 0.0, 1.0,
  84.    LMNULL };
  85.  
  86. float light2[] = {
  87.    AMBIENT,  0.0, 0.0, 0.0,
  88.    LCOLOR,   0.1, 1.0, 0.1,
  89.    POSITION, 0.0, 0.0, 0.0, 1.0,
  90.    LMNULL };
  91.  
  92. float light3[] = {
  93.    AMBIENT,  0.0, 0.0, 0.0,
  94.    LCOLOR,   0.1, 0.1, 1.0,
  95.    POSITION, 0.0, 0.0, 0.0, 1.0,
  96.    LMNULL };
  97.  
  98. float newpos[] = {
  99.    POSITION, 0.0, 0.0, 0.0, 1.0,
  100.    LMNULL };
  101.  
  102. float planemat[] = {
  103.    EMISSION,   0.0, 0.0, 0.0,
  104.    AMBIENT,    0.0, 0.0, 0.0,
  105.    DIFFUSE,    0.4, 0.4, 0.4,
  106.    SPECULAR,   1.0, 1.0, 1.0,
  107.    SHININESS, 30.0,
  108.    LMNULL };
  109.  
  110. float wallmat[] = {
  111.    EMISSION,   0.0, 0.0, 0.0,
  112.    AMBIENT,    0.1, 0.1, 0.1,
  113.    DIFFUSE,    0.8, 0.8, 0.8,
  114.    SPECULAR,   1.0, 1.0, 1.0,
  115.    SHININESS, 20.0,
  116.    LMNULL };
  117.  
  118. float lmodel[] = {
  119.    AMBIENT,0.3,0.3,0.3,
  120.    LOCALVIEWER,1.0,
  121.    ATTENUATION, 1.0, 3.0, 
  122.    LMNULL };
  123.  
  124. extern float frand();
  125.  
  126. char ofile[80];
  127.  
  128.  
  129. /************************************************************/
  130. /* XXX - The following is an excerpt from spin.h from spin  */
  131. /************************************************************/
  132.  
  133. #define POLYGON    1
  134. #define LINES    2
  135. #define TRANSPERENT 3
  136. #define DISPLAY    4
  137. #define LMATERIAL 5
  138.  
  139. #define FASTMAGIC    0x5423
  140.  
  141. typedef struct fastobj {
  142.     int npoints;
  143.     int colors;
  144.     int type;
  145.     int material;
  146.     int display;
  147.     int ablend;
  148.     int *data;
  149. } fastobj;
  150.  
  151. fastobj *readfastobj();
  152.  
  153. /*
  154.  * Wrappers to do either lines or polygons
  155.  */
  156. #define PolyOrLine()    if (lflag == LINES) { \
  157.                 bgnclosedline(); \
  158.             } else if (POLYGON) { \
  159.                 bgnpolygon(); \
  160.             }
  161.  
  162. #define EndPolyOrLine() if (lflag == LINES) { \
  163.                 endclosedline(); \
  164.             } else if (POLYGON) { \
  165.                 endpolygon(); \
  166.             }
  167.  
  168. /************************* end of spin.h excerpt *************************/
  169.  
  170.  
  171. fastobj    *obj = NULL;
  172.  
  173. main(argc, argv)
  174.     int argc;
  175.     char **argv;
  176. {
  177.     if (argc > 1)
  178.     {
  179.     int i;
  180.  
  181.     for (i=0; argv[1][i] != '/' && argv[1][i] != '\0'; i++);
  182.     if (argv[1][i] != '/')
  183.     {
  184.         strcpy(ofile, "/usr/demos/data/models/");
  185.         strcat(ofile, argv[1]);
  186.     }
  187.     else
  188.         strcpy(ofile, argv[1]);
  189.  
  190.     if (obj = readfastobj(ofile))
  191.         objecton = TRUE;
  192.     }
  193.  
  194.     ballsize = .04;
  195.     ballscale = 1.0 - ballsize;
  196.  
  197.     initialize(argv);
  198.  
  199.     make_menu();
  200.  
  201.     resetballs();
  202.  
  203.     getsize(&xsize, &ysize);
  204.  
  205.     mmode(MVIEWING);
  206.     perspective(600, (float)xsize/ysize, EYEZ-2.0, EYEZ+2.0);
  207.  
  208.     translate(0.0, 0.0, -EYEZ);
  209.  
  210.     /* Use local lights for the box */
  211.     lmbind(LIGHT0, 1);
  212.     lmbind(LIGHT1, 2);
  213.     lmbind(LIGHT2, 3);
  214.  
  215.     while(1)  {
  216.     calcbox();
  217.     if (!freeze)
  218.         calcball();
  219.     drawimage();
  220.     }
  221. }
  222.  
  223. resetballs()
  224. {
  225.     register short i;
  226.  
  227.     balls[0].color[R] = 255;
  228.     balls[0].color[G] = 64;
  229.     balls[0].color[B] = 64;
  230.     balls[1].color[R] = 64;
  231.     balls[1].color[G] = 255;
  232.     balls[1].color[B] = 64;
  233.     balls[2].color[R] = 64;
  234.     balls[2].color[G] = 64;
  235.     balls[2].color[B] = 255;
  236.     for (i = 0; i < TOTALBALLS; i++) {
  237.     balls[i].p[0] = 0.0;
  238.     balls[i].p[1] = 0.0;
  239.     balls[i].p[2] = 0.0;
  240.     balls[i].d[0] = .1*frand();
  241.     balls[i].d[1] = .1*frand();
  242.     balls[i].d[2] = .1*frand();
  243.     }
  244. }
  245.  
  246. drawimage()
  247. {
  248.     register short i;
  249.  
  250.     check_q();
  251.  
  252.     zbuffer(FALSE);
  253.     if (machine == MACH_GT) {
  254.     czclear(0, 0);    /* Simultaneously clear z and color buffers */
  255.     } else {
  256.        /* czclear(0, 0x7fffff); */
  257.        czclear(0, getgdesc(GD_ZMAX));
  258.      }
  259.     lmbind(LMODEL, 1);
  260.  
  261.     pushmatrix();
  262.     rotate(ry, 'y' );
  263.     rotate(rx, 'x' );
  264.  
  265.     for (i=0; i < TOTALBALLS; i++) {
  266.     newpos[1] = balls[i].p[0];
  267.     newpos[2] = balls[i].p[1];
  268.     newpos[3] = balls[i].p[2];
  269.     lmdef( DEFLIGHT, i+1, 6, newpos );
  270.     }
  271.  
  272.     lmbind(MATERIAL, 1);
  273.     drawbox();
  274.  
  275.     zbuffer(TRUE); 
  276.  
  277.     if (objecton)
  278.     {
  279.     lmbind(MATERIAL, 2);
  280.     pushmatrix();
  281.     scale(1.5, 1.5, 1.5);
  282.     rotate(1800, 'z');
  283.     if (spin)
  284.     {
  285.         orx += 50;
  286.         ory += 50;
  287.     }
  288.     rotate(orx, 'x');
  289.     rotate(ory, 'y');
  290.     drawfastobj(obj);
  291.     popmatrix();
  292.     }
  293.  
  294.     lmbind(LMODEL, 0);
  295.  
  296.     for (i=0; i < TOTALBALLS; i++) {
  297.     if (lighton[i])
  298.     {
  299.         pushmatrix();
  300.         translate( balls[i].p[0],balls[i].p[1],balls[i].p[2] );
  301.         c3i(balls[i].color);
  302.         drawball();
  303.         popmatrix();
  304.     }
  305.     }
  306.  
  307.     popmatrix();
  308.     swapbuffers();
  309. }
  310.  
  311.  
  312. initialize(argv)
  313. char **argv;
  314. {
  315.     long time();
  316.  
  317.     {    /* Open window with name of executable */
  318.         char *t, *strrchr();
  319.         winopen((t=strrchr(argv[0], '/')) != NULL ? t+1 : argv[0]);
  320.     }
  321.    if (getgdesc(GD_BITS_NORM_SNG_RED) < 3)
  322.     {
  323.         system("inform 'Your system must support RGB mode to run bounce'");
  324.         exit(1);
  325.     }
  326.     if (getgdesc(GD_BITS_NORM_ZBUFFER) == 0)
  327.     {
  328.         system("inform 'Your system must have a z-buffer to run bounce'");
  329.        exit(1);
  330.    }
  331.  
  332.  
  333.     doublebuffer();
  334.     RGBmode();
  335.     gconfig();
  336.  
  337.     gversion(machinetype);
  338.     if (strncmp (machinetype,"GL4DPI", strlen("GL4DPI")) == 0)
  339.         machine = MACH_PI;
  340.     else if (strncmp (machinetype, "GL4DGT", strlen("GL4DGT")) == 0)
  341.         machine = MACH_GT;
  342.     else if (strncmp (machinetype, "GL4DVGX", strlen("GL4DVGX")) == 0)
  343.         machine = MACH_VGX;
  344.     else machine = MACH_G;
  345.  
  346.     /* Setup to use simultaneous z and color buffer clear */
  347.     switch(machine)
  348.     {
  349.     case MACH_GT:
  350.         zfunction(ZF_GEQUAL);
  351.         lsetdepth(0x7fffff, 0x0ff);
  352.         break;
  353.     case MACH_PI:
  354.     case MACH_G:
  355.     case MACH_VGX:
  356.     default:
  357.         /*
  358.          *  use default z setup
  359.          */
  360.         break;
  361.     }
  362.  
  363.     initobjects();
  364.  
  365.     srand((unsigned)time(0));
  366.  
  367.     lmdef(DEFLMODEL, 1, 10, lmodel);
  368.     lmdef(DEFMATERIAL, 1, 19, wallmat);
  369.     lmdef(DEFMATERIAL, 2, 19, planemat);
  370.     lmdef(DEFLIGHT, 1, 14, light1);
  371.     lmdef(DEFLIGHT, 2, 14, light2);
  372.     lmdef(DEFLIGHT, 3, 14, light3);
  373.  
  374.     qdevice(RIGHTMOUSE);
  375.     qdevice(MIDDLEMOUSE);
  376.     qdevice(LEFTMOUSE);
  377.     qdevice(ESCKEY);
  378. }
  379.  
  380.  
  381. initobjects()
  382. {
  383.     register float u,v,du,dv;
  384.     register short i,j;
  385.  
  386.     du = 2.0*3.1416/UDIV;
  387.     dv = 3.1416/VDIV;
  388.  
  389.     u = 0.;
  390.     for (i=0; i <= UDIV; i++) {
  391.     v = 0.;
  392.     for (j=0; j <= VDIV; j++) {
  393.         ballobj[i][j][X] = ballsize*cos(u)*sin(v);
  394.         ballobj[i][j][Y] = ballsize*sin(u)*sin(v);
  395.         ballobj[i][j][Z] = ballsize*cos(v);
  396.         ballobj[i][j][W] = 1.0;
  397.         v += dv;
  398.     }
  399.     u += du;
  400.     }
  401.  
  402.     for (i=0; i <= WALLGRID; i++) {
  403.     for (j=0; j <= WALLGRID; j++) {
  404.         wallobj[i][j][X] = -1.0 + 2.0*i/WALLGRID;
  405.         wallobj[i][j][Y] = -1.0 + 2.0*j/WALLGRID;
  406.         wallobj[i][j][Z] = 1.0;
  407.         wallobj[i][j][W] = 1.0;
  408.     }
  409.     }
  410.  
  411.     for (i=0; i <= WALLGRID; i++) {
  412.     for (j=0; j <= WALLGRID; j++) {
  413.         wallnorms[i][j][X] = wallobj[i][j][X] + wallnorm[X]*0.1;
  414.         wallnorms[i][j][Y] = wallobj[i][j][Y] + wallnorm[Y]*0.1;
  415.         wallnorms[i][j][Z] = wallobj[i][j][Z] + wallnorm[Z]*0.1;
  416.     }
  417.     }
  418. }
  419.  
  420.  
  421. drawball()
  422. {
  423.     register int i,j;
  424.  
  425.     for (i=0; i < UDIV; i++) {
  426.     for (j=0; j < VDIV; j++) {
  427.         bgnpolygon();
  428.         v4f( ballobj[i][j] );
  429.         v4f( ballobj[i+1][j] );
  430.         v4f( ballobj[i+1][j+1] );
  431.         v4f( ballobj[i][j+1] );
  432.         endpolygon();
  433.     }
  434.     }
  435. }
  436.  
  437.  
  438. drawface()
  439. {
  440.     register int i,j;
  441.  
  442.     n3f(wallnorm);
  443.     for (i=0; i < WALLGRID; i++) {
  444.     bgntmesh();
  445.     for (j=0; j <= WALLGRID; j++) {
  446.         v3f(wallobj[i][j]);
  447.         v3f(wallobj[i+1][j]);
  448.     }
  449.     endtmesh();
  450.     }
  451. }
  452.  
  453.  
  454. drawnorms()
  455. {
  456.     register int i,j;
  457.  
  458.     lmbind(LMODEL, 0);
  459.     RGBcolor(255, 0, 255);
  460.     for (i=0; i <= WALLGRID; i++) {
  461.     for (j=0; j <= WALLGRID; j++) {
  462.         bgnline();
  463.         v3f(wallobj[i][j]);
  464.         v3f(wallnorms[i][j]);
  465.         endline();
  466.     }
  467.     }
  468.     lmbind(LMODEL, 1);
  469. }
  470.  
  471.  
  472. drawbox()
  473. {
  474.     pushmatrix();
  475.  
  476. /*  drawface();        */
  477.     rotate(900, 'y');
  478.     drawface();
  479.     if (normson) drawnorms();
  480.     rotate(900, 'y');
  481.     drawface();
  482.     if (normson) drawnorms();
  483.     rotate(900, 'y');
  484. /*  drawface();        */
  485.     rotate(-900, 'x');
  486.     drawface();
  487.     if (normson) drawnorms();
  488.     rotate(1800, 'x');
  489. /*  drawface();        */
  490.     popmatrix();
  491. }
  492.  
  493.  
  494. calcbox()
  495. {
  496.     rx = -800*getvaluator(MOUSEY)/getgdesc(GD_YPMAX) - 50;
  497.     ry = 50 + 800*getvaluator(MOUSEX)/getgdesc(GD_XPMAX);
  498. }
  499.  
  500.  
  501. calcball()
  502. {
  503.     register short i,j;
  504.  
  505.     for (j=0; j < TOTALBALLS; j++) {
  506.     for (i=0; i < 3; i++) {
  507.         balls[j].p[i] += balls[j].d[i];
  508.         if (fabs(balls[j].p[i]) > ballscale) {
  509.         balls[j].p[i] = (balls[j].p[i] > 0.0) ?
  510.         ballscale : -ballscale;
  511.         balls[j].d[i] = -balls[j].d[i];
  512.         }
  513.     }
  514.     }
  515. }
  516.  
  517.  
  518. float frand()
  519. {
  520.     return 2.0*(rand()/32768.0 - .5);
  521. }
  522.  
  523.  
  524. check_q()
  525. {
  526.     short val;
  527.  
  528.     while(qtest())
  529.     {
  530.     switch(qread(&val))
  531.     {
  532.         case REDRAW:
  533.             reshapeviewport();
  534.             break;
  535.         case ESCKEY:
  536.             if (!val)
  537.             {
  538.                 gexit();
  539.                 exit(0);
  540.             }
  541.             break;
  542.         case MENUBUTTON:
  543.         if (val)
  544.             switch(dopup(menu)) {
  545.             case 1:
  546.                 if (lighton[0] = !lighton[0])
  547.                 lmbind(LIGHT0, 1);
  548.                 else
  549.                 lmbind(LIGHT0, 0);
  550.                 break;
  551.             case 2:
  552.                 if (lighton[1] = !lighton[1])
  553.                 lmbind(LIGHT1, 2);
  554.                 else
  555.                 lmbind(LIGHT1, 0);
  556.                 break;
  557.             case 3:
  558.                 if (lighton[2] = !lighton[2])
  559.                 lmbind(LIGHT2, 3);
  560.                 else
  561.                 lmbind(LIGHT2, 0);
  562.                 break;
  563.             case 4:
  564.                 freeze =  !freeze;
  565.                 break;
  566.             case 5:
  567.                 if (obj)
  568.                 objecton =  !objecton;
  569.                 else
  570.                 exit();
  571.                 break;
  572.             case 6:
  573.                 spin =  !spin;
  574.                 break;
  575.             case 7:
  576.                 exit();
  577.                 break;
  578.             }
  579.             make_menu();
  580.         break;
  581.         default:
  582.             break;
  583.     }
  584.     }
  585. }
  586.  
  587.  
  588. make_menu()
  589. {
  590.     char buf[256];
  591.  
  592.     if (menu)
  593.     freepup(menu);
  594.  
  595.     strcpy(buf, "bounce %t");
  596.  
  597.     if (lighton[0])
  598.     strcat(buf, "|red light off");
  599.     else
  600.     strcat(buf, "|red light on");
  601.     if (lighton[1])
  602.     strcat(buf, "|green light off");
  603.     else
  604.     strcat(buf, "|green light on");
  605.     if (lighton[2])
  606.     strcat(buf, "|blue light off");
  607.     else
  608.     strcat(buf, "|blue light on");
  609.  
  610.     if (freeze)
  611.     strcat(buf, "|unfreeze lights");
  612.     else
  613.     strcat(buf, "|freeze lights");
  614.  
  615.     if (obj)
  616.     {
  617.     if (objecton)
  618.         strcat(buf, "|object off");
  619.     else
  620.         strcat(buf, "|object on");
  621.     if (spin)
  622.         strcat(buf, "|object spin off");
  623.     else
  624.         strcat(buf, "|object spin on");
  625.     }
  626.  
  627.     strcat(buf, "|exit");
  628.  
  629.     menu = defpup(buf);
  630. }
  631.  
  632. /**********************************************************/
  633. /* XXX - The following is a clone of fastobj.c from spin  */
  634. /**********************************************************/
  635.  
  636.  
  637. fastobj *readfastobj(name)
  638. char *name;
  639. {
  640.     FILE *inf;
  641.     fastobj *obj;
  642.     int i;
  643.     int nlongs;
  644.     int magic;
  645.     int *ip;
  646.     char filename[512];
  647.  
  648.     inf = fopen(name,"r");
  649.     if(!inf) {
  650.       sprintf(filename,"%s",name);
  651.     inf = fopen(filename,"r");
  652.     if(!inf) {
  653.         fprintf(stderr,"readfast: can't open input file %s\n",name);
  654.         exit(1);
  655.     }
  656.     }
  657.     fread(&magic,sizeof(int),1,inf);
  658.     if(magic != FASTMAGIC) {
  659.     fprintf(stderr,"readfast: bad magic in object file\n");
  660.     fclose(inf);
  661.     exit(1);
  662.     }
  663.     obj = (fastobj *)malloc(sizeof(fastobj));
  664.     fread(&obj->npoints,sizeof(int),1,inf);
  665.     fread(&obj->colors,sizeof(int),1,inf);
  666.  
  667.     /*
  668.      * Insure that the data is quad-word aligned and begins on a page
  669.      * boundary.  This shields us from the performance loss which occurs 
  670.      * whenever we try to fetch data which straddles a page boundary  (the OS
  671.      * has to map in the next virtual page and re-start the DMA transfer).
  672.      */
  673.     nlongs = 8 * obj->npoints;
  674.     obj->data = (int *) malloc(nlongs*sizeof(int) + 4096);
  675.     obj->data = (int *) (((int)(obj->data)) + 0xfff);
  676.     obj->data = (int *) (((int)(obj->data)) & 0xfffff000);
  677.  
  678.     for (i = 0, ip = obj->data;  i < nlongs/4;  i++, ip += 4)
  679.     fread(ip, 3 * sizeof(int), 1, inf);
  680.     fclose(inf);
  681.     return obj;
  682. }
  683.  
  684.  
  685. drawfastobj(obj)
  686. fastobj *obj;
  687. {
  688.     register int *p, *end;
  689.     register int npolys;
  690.  
  691.     p = obj->data;
  692.     end = p + 8 * obj->npoints;
  693.  
  694.     if(obj->colors) {
  695.     npolys = obj->npoints/4;
  696.     p = obj->data;
  697.     while(npolys--) {
  698.         PolyOrLine();
  699.         c3i(p);
  700.         v3f((float *)p+4);
  701.         c3i(p+8);
  702.         v3f((float *)p+12);
  703.         c3i(p+16);
  704.         v3f((float *)p+20);
  705.         c3i(p+24);
  706.         v3f((float *)p+28);
  707.         EndPolyOrLine();
  708.         p += 32;
  709.     }
  710.     } else {
  711.     while ( p < end) {
  712.         PolyOrLine();
  713.         n3f((float *)p);
  714.         v3f((float *)p+4);
  715.         n3f((float *)p+8);
  716.         v3f((float *)p+12);
  717.         n3f((float *)p+16);
  718.         v3f((float *)p+20);
  719.         n3f((float *)p+24);
  720.         v3f((float *)p+28);
  721.         EndPolyOrLine();
  722.         p += 32;
  723.     }
  724.     }
  725. }
  726.  
  727.  
  728. /*
  729.  * objmaxpoint
  730.  *
  731.  * find the vertex farthest from the origin,
  732.  * so we can set the near and far clipping planes tightly.
  733.  */
  734.  
  735. #define MAXVERT(v) if ( (len = sqrt(    (*(v))  *  (*(v))  +           \
  736.                     (*(v+1)) * (*(v+1)) +           \
  737.                     (*(v+2)) * (*(v+2)) )) > max)  \
  738.             max = len;
  739.  
  740. float
  741. objmaxpoint(obj)
  742. fastobj *obj;
  743. {
  744.     register float *p, *end;
  745.     register int npolys;
  746.     register float len;
  747.     register float max = 0.0;
  748.  
  749.     p = (float *) (obj->data);
  750.  
  751.     if (obj->colors) {
  752.     npolys = obj->npoints/4;
  753.     while(npolys--) {
  754.         MAXVERT(p+4);
  755.         MAXVERT(p+12);
  756.         MAXVERT(p+20);
  757.         MAXVERT(p+28);
  758.         p += 32;
  759.     }
  760.     } else {
  761.     end = p + 8 * obj->npoints;
  762.     while ( p < end) {
  763.         MAXVERT(p+4);
  764.         MAXVERT(p+12);
  765.         MAXVERT(p+20);
  766.         MAXVERT(p+28);
  767.         p += 32;
  768.     }
  769.     }
  770.  
  771.     return max;
  772. }
  773.